package com.xh.tools;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;

/**
 * @author xh
 * @description 文件工具类
 */
public class FileUtils {

    private static final String PERIOD = ".";
    private static final String SLASH = "/";
    private static final String DEFAULT_CONTENT_TYPE = "text/plain";

    /**
     * 获取文件名
     *
     * @param filePath 文件路径
     * @return 文件名
     */
    public static String getFileName(String filePath) {
        if (StringUtils.isBlank(filePath)) {
            return "";
        }
        String sparator = SLASH;
        if (filePath.contains("\\")) {
            sparator = "\\";
        }
        return filePath.substring(filePath.lastIndexOf(sparator) + 1);
    }

    /**
     * 获取文件后缀
     *
     * @param filePath 文件路径
     * @return 文件后缀
     */
    public String getFileSuffix(String filePath) {
        if (StringUtils.isBlank(filePath) || !filePath.contains(PERIOD)) {
            return "";
        }
        return filePath.substring(filePath.lastIndexOf(PERIOD) + 1);
    }

    /**
     * 获取文件内容类型
     *
     * @param filePath 文件路径
     * @return 文件内容类型
     */
    public String getFileContentType(String filePath) {
        if (StringUtils.isBlank(filePath)) {
            return DEFAULT_CONTENT_TYPE;
        }
        try {
            return Files.probeContentType(new File(filePath).toPath());
        } catch (IOException e) {
            return DEFAULT_CONTENT_TYPE;
        }
    }

    /**
     * 获取文件路径下的所有文件路径
     *
     * @param filePath 文件路径
     * @return 文件路径下的所有文件路径
     */
    public static List<String> getFilePaths(String filePath) {
        List<String> list = new ArrayList<>();
        doListFilePaths(filePath, list);
        return list;
    }

    /**
     * 获取文件路径下的所有文件
     *
     * @param filePath 文件路径
     * @return 文件路径下的所有文件
     */
    public static List<File> getFiles(String filePath) {
        List<File> list = new ArrayList<>();
        doListFiles(filePath, list);
        return list;
    }

    /**
     * 删除文件
     *
     * @param filePath 文件路径
     */
    public static void deleteFile(String filePath) {
        if (StringUtils.isBlank(filePath)) {
            return;
        }
        File file = new File(filePath);
        if (!file.exists()) {
            return;
        }

        if (file.isFile()) {
            boolean delete = file.delete();
            System.out.printf("删除文件[%s]-%s%n", filePath, delete);
        } else {
            File[] files = file.listFiles();
            if (files == null || files.length == 0) {
                boolean delete = file.delete();
                System.out.printf("删除文件[%s]-%s%n", filePath, delete);
            } else {
                throw new RuntimeException("文件下还有子文件，无法删除！");
            }
        }
    }

    /**
     * 递归删除所有文件
     *
     * @param filePath 文件路径
     */
    public static void deleteFiles(String filePath) {
        if (StringUtils.isBlank(filePath)) {
            return;
        }
        File file = new File(filePath);
        if (!file.exists()) {
            return;
        }

        if (file.isFile()) {
            boolean delete = file.delete();
            System.out.printf("删除文件[%s]-%s%n", filePath, delete);
        } else {
            File[] files = file.listFiles();
            if (files == null) {
                return;
            }
            for (File f : files) {
                deleteFiles(f.getAbsolutePath());
            }
            boolean delete = file.delete();
            System.out.printf("删除文件[%s]-%s%n", filePath, delete);
        }
    }

    /**
     * 复制文件内容
     *
     * @param sourceFilePath 源文件路径
     * @param targetPath     目标文件路径
     */
    public void copyFile(String sourceFilePath, String targetPath) {
        if (StringUtils.isBlank(sourceFilePath) || StringUtils.isBlank(targetPath)) {
            return;
        }
        try {
            Files.copy(new File(sourceFilePath).toPath(), new File(targetPath).toPath());
        } catch (IOException e) {
            throw new RuntimeException(String.format("文件复制[%s->%s]失败：%s",
                    sourceFilePath, targetPath, e.getMessage()));
        }
    }

    /**
     * 文件复制
     *
     * @param ips        源文件输入流
     * @param targetPath 目标文件路径
     */
    public void copyFile(InputStream ips, String targetPath) {
        if (ips == null || StringUtils.isBlank(targetPath)) {
            return;
        }
        byte[] buffer = new byte[1024 * 2];
        int len = 0;
        FileOutputStream ops = null;
        try {
            ops = new FileOutputStream(targetPath);
            while ((len = ips.read(buffer)) != -1) {
                ops.write(buffer, 0, len);
            }
        } catch (Exception e) {
            throw new RuntimeException(String.format("写入文件[%s]失败：%s", targetPath, e.getMessage()));
        } finally {
            try {
                if (ops != null) {
                    ops.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取文件路径
     *
     * @param filePath 文件路径
     * @param list     列表
     */
    private static void doListFilePaths(String filePath, List<String> list) {
        if (StringUtils.isBlank(filePath)) {
            return;
        }
        File file = new File(filePath);
        if (file.isFile()) {
            list.add(filePath);
        } else {
            File[] files = file.listFiles();
            if (files == null) {
                return;
            }
            for (File f : files) {
                doListFilePaths(f.getAbsolutePath(), list);
            }
        }
    }

    /**
     * 列出文件路径
     *
     * @param filePath 文件路径
     * @param list     文件列表
     */
    private static void doListFiles(String filePath, List<File> list) {
        if (StringUtils.isBlank(filePath)) {
            return;
        }
        File file = new File(filePath);
        if (file.isFile()) {
            list.add(file);
        } else {
            File[] files = file.listFiles();
            if (files == null) {
                return;
            }
            for (File f : files) {
                doListFiles(f.getAbsolutePath(), list);
            }
        }
    }
}
